home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 4,101 to 4,200 / aol-file-protocol-4400-4101-to-4200.zip / AOLDLs / ADV - Articles & Misc / DYA TechNote #03_ SHR Animation / TN.DYA.03.V1.1 < prev   
Text File  |  2014-11-30  |  18KB  |  411 lines

  1. *-----------------------------------------------------------------------------*
  2.   DYA TechNote #3: Basic animation theories.
  3.  
  4.        Written by: Jim Maricondo          June 10, 1990       Version 1.1
  5. *-----------------------------------------------------------------------------*
  6.  
  7.                Although this technote is not copyrighted in any way, I'd
  8. appreciate it if you asked permission first if you wanted to distribute it in a
  9. non-electronic form.  Thanks.  Please tell me what you think of it.  I'm still
  10. deciding whether to release DYA TechNotes 1 and 2...  Oh well, here is the
  11. technote.  It's not that professional, because I figured why put all that extra
  12. time into it if hardly anyone's going to see it?  If you have any questions,
  13. email me or post them.
  14.  
  15.                Welcome to DYA TechNote number three on basic animation
  16. theories.  Because of the GS's lack of speed, programming decent animation is
  17. often a challenge.  We all take for granted other people's programs out there
  18. that do all kinds of neat stuff, but then we think, "Now how in the hell would
  19. I do that?"  Also, please note that all the stuff talked about in this TechNote
  20. refers to 320 mode.  Note that this is only a BASIC discussion; I'm not going
  21. to go into all kinds of detail about the screen in memory.  If you want detail,
  22. buy the Hardware Reference.  Note also that whenever you are using any memory
  23. that is not normally SHR memory (like bank $01 and your background bank) be
  24. sure to allocate it thru the Memory Manager, and if you can't get it, display
  25. an error message and quietly quit.
  26.  
  27.  
  28. THE SHR SCREEN
  29.  
  30.                First let's talk about the SuperHiRes (SHR) screen in memory.
  31. The pixel data itself starts at $E12000, and runs to $E19D00.  Each pixel on
  32. the screen is one nibble (1/2 byte) in memory.  Thus a scanline of 320 pixels
  33. takes up 160 ($A0) bytes in memory.  ($A0 x 200 = $7D00.)  Next after the pixel
  34. data are the ScanLine Control Bytes, or SCB's.  There is one of these for every
  35. scan line.  They technically run from $E19D00 thru $E19D67.  The SCB for line
  36. one is at $E19D00, the SCB for line two is at $E19D01, etc.  SCB's tell whether
  37. the line is 320 pixels wide or 640 pixels wide, whether the line will generate
  38. interrupts, whether color fill mode is enabled on that line, and which palette
  39. that line will use.  Palette data runs from $E19E00 to $E19FFF.  Each color in
  40. a palette is two bytes, and there are 16 colors in a palette, and 16 palettes.
  41. All palette data is stored in memory sequentially.
  42.  
  43.  
  44.  
  45. BEGINNING ANIMATION AND SPEEDING THINGS UP SOME
  46.  
  47.                The obvious method of animation is just to load and store values
  48. to the screen in bank $E1.  However, once you start to do anything major, this
  49. becomes too slow and awkward for much.  All values written and read from bank
  50. $E1 are written and read at 1 mHZ!  It's bad enough the GS is slow, but who
  51. wants to do speed eating animation at the speed of a IIe?  This is where
  52. shadowing comes in.  By flipping the correct softswitch, whatever written in
  53. bank $01 is automatically also written to bank $E1 at fast 2.8 mHZ!  This is
  54. the first step in efficient animation.
  55.  
  56.  
  57.  
  58. PRESERVING THE BACKGROUND AND AVOIDING FLICKER
  59.  
  60.                So we're happily doing all our drawing to bank $01 now, but how
  61. can we animate shapes over a background that isn't just a solid color?  Use
  62. another bank just for the background.  I would recommend use of banks $06, $07,
  63. $08, or $09 because these banks aren't used that often by the system.  In this
  64. example, I'll use bank $09.  After allocating $092000 to $09A000 successfully
  65. thru the memory manager, we will procede to load our background picture into
  66. $092000.  We then allocate $012000 to $01A000 thru the memory manager, and upon
  67. no error we continue.  Now, the basic theory behind preserving the background
  68. is this:
  69.  
  70. 1) Copy the background from the background bank ($09 here) to bank $01.
  71. 2) Draw your shapes over the background in bank $01.
  72. 3) Repeat.
  73.  
  74. However, this is also very slow as we are doing a lot of stuff we don't really
  75. need to do.  We can help to optimize this method by only ONLY copying the
  76. background in bank $09 over the area where the shape OCCUPIED in bank $01, not
  77. copying the whole background over all of bank $01.
  78.  
  79.                Still, this method is flawed.  Often, your shapes will flicker
  80. beyond belief.  Let's present a new method around this:
  81.  
  82. 1) Copy the whole background to bank $01.
  83. 2) Turn off shadowing.
  84. 3) Draw shapes in bank $01, thus drawing them over the background copied to
  85. bank $01.
  86. 4) Turn on shadowing, and copy everything onto itself in bank $01, thus quickly
  87. transferring it to bank $E1 and onto the screen.
  88. 5) Turn off shadowing.
  89. 6) Copy background from bank $09 over only the area where the shape was.
  90. 7) Repeat steps 3 thru 6.
  91.  
  92.                This way you never see the shape being erased and then drawn
  93. again, you only see a nice new frame of animation where the shape is somewhere
  94. different.  There is NO flicker!
  95.  
  96.  
  97.  
  98. SCREEN UPDATE TECHNIQUES - MVN
  99.  
  100.                While there is no flicker, this method can be slow.  One way to
  101. speed it up is to use an efficient method of copying everything onto itself.
  102. The easiest method to understand, but which is very slow, is to use MVN.  Here
  103. is an example of copying everything onto itself using MVN.
  104.  
  105. MVNUpdate      anop
  106.  
  107.                shortm
  108.                lda   $E0C035            turn on SHR shadowing
  109.                and   #$F7
  110.                sta   $E0C035
  111.                longm
  112.  
  113.                ldx   #$2000             start at $2000
  114.                txy
  115.                lda   #$7E00-1           screen data is $7E00 bytes
  116.                mvn   $012000,$E12000    use shadowing to quickly copy each byte
  117.                                         onto itself
  118.                phk                      always reset data bank after mvn
  119.                plb
  120.  
  121.                shortm
  122.                lda   $E0C035            turn off SHR shadowing
  123.                ora   #$08
  124.                sta   $E0C035
  125.                longm
  126.  
  127.  
  128.                For the technical types, this method does it at 7 cycles a byte.
  129. There is a method twice as fast using the stack.  But in order to understand
  130. it, we must understand the stack, and how it can be used in animation.  A quick
  131. look at the 65816's instruction set shows you that the operations that take the
  132. least time to complete involve the stack.  There is another softswitch we can
  133. flip that will let us have the stack in bank $01 instead of in bank $00.  So we
  134. can align the stack pointer to the SHR screen, and by pushing values onto the
  135. stack, we'd be "pushing" pixels onto the screen.  When the stack is here, we
  136. don't need to PULL off everything we pushed onto it as we do in normal
  137. programming.
  138.  
  139.  
  140.  
  141. SCREEN UPDATE TECHNIQUES - PEI
  142.  
  143.                Next, let's take the PEI instruction.  PEI stands for Push
  144. Effective Indirect.  PEI ($xx) and PEI $xx mean the same.  PEI $xx is the
  145. equivalent of "lda $xx, pha".  PEI takes the direct page location specified by
  146. the operand and pushes it.  Now if we align the stack and the direct page in
  147. the correct way, a list of PEI's can actually update the screen for us!  I know
  148. this may seem a little far fetched as of now.  I know it will probably take
  149. time to sink in.  First, let me present the stack based equivalent of the MVN
  150. method above.  Then I'll explain in more detail.
  151.  
  152. StackUpdate    anop
  153.  
  154.                php              ; save whether interrupts were enabled at first
  155.                sei                      disable interrupts
  156.  
  157.                phd                      save old direct page register
  158.                tsc                      save off old stack pointer
  159.                sta   StackTemp
  160.  
  161.                shortm
  162.                lda   $E0C035            turn on SHR shadowing
  163.                and   #$F7
  164.                sta   $E0C035
  165.                lda   $E0C068            turn on bank $01 direct page & stack
  166.                ora   #$30
  167.                sta   $E0C068
  168.                longm
  169.  
  170.                lda   #$9D00
  171.                tcs
  172.  
  173.                lda   #$9D00-$FF
  174.                tcd
  175.  
  176.                ldy   #125               repeat loop 125 times --> 125 = $7D,
  177.                                         and since we update $100 bytes per one
  178.                                         execution of this loop, $7D x $100 =
  179.                                         $7D00, or all of the SHR pixel data
  180.                sec
  181.  
  182. loop           anop
  183.                pei   $FE
  184.                pei   $FC
  185.                pei   $FA
  186.  
  187.                ...                      all the inbetween pei's...
  188.  
  189.                pei   $04
  190.                pei   $02
  191.                pei   $00
  192.  
  193.                tdc
  194.                sbc   #$FF               subtract $FF from the direct page reg.
  195.                tcd                      (see explaination below!)
  196.  
  197.                dey                      done 125 repetitions yet?
  198.                jne   loop               if not, loop again
  199.  
  200.                shortm
  201.                lda   $E0C035            turn off SHR shadowing
  202.                ora   #$08
  203.                sta   $E0C035
  204.                lda   $E0C068            turn off bank $01 dp/stack
  205.                and   #$CF
  206.                sta   $E0C068
  207.                longm
  208.  
  209.                lda   StackTemp          restore original stack pointer
  210.                tcs
  211.                pld                      restore original direct page pointer
  212.  
  213.                plp                      restore original interrupt status
  214.  
  215.                ... (your code here)
  216.  
  217. StackTemp      ds    2
  218.  
  219.  
  220.                We have to disable interrupts, because if a routine interrupts
  221. in the middle of the update, and the routine uses the stack (ALL interrupts do
  222. no matter what, unless you rewrite the system interrupt manager, but that's
  223. another thing) and since whatever pushed onto the stack goes to the SHR screen,
  224. you will get parts of the screen messed up.
  225.  
  226.                It is best to try to have the direct page register have a lo
  227. byte of 00.  Because when the low byte is zero, each PEI instruction is one
  228. cycle faster.  One cycle might not seem like a lot, but oodles of PEI
  229. instructions would add up!  The above example does not do this, as I am not in
  230. the mood to rewrite it to keep the lo bite of the direct page register zero.
  231.  
  232.                The above stack based update routine is only meant as an
  233. example.  I would not recommend updating the WHOLE screen for each frame, as
  234. even using the stack for updates, the WHOLE screen can only be updated at about
  235. two to three frames a second (fps).  It is best to only update the part of the
  236. screen that needs updating using the stack.  I will leave writing a modified
  237. version of the above routine that only updates the area where you want it to
  238. you, and I will also leave implementing code to make sure the lo byte of the
  239. direct page register is zero also to you.
  240.  
  241.                We align the direct page pointer always $FF bytes ahead in
  242. memory BEFORE the stack.  Let me try to explain this.  Say the direct page
  243. register is set to $9D00 and the stack is set to $9DFF.  When we PEI $FE, it is
  244. really saying "load $9DFE {the value of the operand added to the value of the
  245. direct page register} and push it to $9DFE {the stack pointer is decremented,
  246. and then the value at that direct page location is stored to the value
  247. of the new stack pointer, $9DFE}."  This is also why at the end of the update,
  248. we only need to subtract $FF from the direct page, and NOT the stack; because
  249. the stack is automatically decremented, and the direct page is not.
  250.  
  251.                I have not actually tested the above code, as I don't update the
  252. entire screen for one frame, but theoretically it should work fine.  Also, all
  253. data in your original program's direct page will be perfectly preserved!
  254.  
  255.  
  256.  
  257. USING THE STACK FOR SCROLLING
  258.  
  259.                This gets even more confusing than just updating the screen!  I
  260. strongly suggest that if this is all new to you, don't bother with this section
  261. until you really understand stack based updates!
  262.  
  263.                By carefully manipulating the stack and direct page, you can use
  264. the stack to do ULTRA FAST scrolling, as in the intro screen to my Photon
  265. program.  This method has its pro's and con's.  While it CAN be VERY fast, it
  266. can really fry your brain out!  It is a big pain in the a$$ to understand, and
  267. even harder to program in the first place!  Also, you CAN mess up and make it
  268. SLOW.  It would still be faster than normal methods, but slower than how fast
  269. it COULD be.  In addition to making sure the lo byte of the DP register is
  270. always zero, you need to speed it up by only making it move the area of the
  271. screen that needs scrolling, not just the entire screen.  This is really hard.
  272. I spent 4 hours frying my brain out on the stack scroll routine that my Photon
  273. program uses.  You need to know a great deal about the GS's hardware, and about
  274. programming in assembly.  Also, some scrollings are not possible using the
  275. stack.  It has a very limited use.  For instance, you can't scroll stuff from
  276. right to left using PEI, (you have to use pla, sta $xx instead), and you can't
  277. scroll up one line and keep the lo byte of the DP register zero.  Read with
  278. caution!
  279.  
  280.                Next I will present what I feel is the easiest stack based
  281. scroll to understand.  It scrolls the ENTIRE screen down one line.  To the
  282. non-programmer it looks slow.  But to the programmer, it is a massive speed up
  283. over doing (lda $012000,x inx ... sta $012000,x ... ).  It keeps the lo byte of
  284. the DP register zero tho.  I will leave you to figure out how to repeat it
  285. several times.  Just remember once you change the stack to bank 01, you can't
  286. use the stack for anything EXCEPT graphics.  That means NO jsr's, jsl's, pha's,
  287. phx's, per's, phy's, etc.  ONLY PEI's and if you are pushing PEA $xxxx onto the
  288. screen!  Most importantly you must NOT make any toolbox or GS/OS calls while
  289. the stack and direct page are in bank 01!!!
  290.  
  291. MoveDown1Line  anop
  292.  
  293.                php              ; save whether interrupts were enabled at first
  294.                sei                      disable interrupts
  295.  
  296.                phd                      save old direct page register
  297.                tsc                      save off old stack pointer
  298.                sta   StackTemp
  299.  
  300.                shortm
  301.                lda   $E0C035            turn on SHR shadowing
  302.                and   #$F7
  303.                sta   $E0C035
  304.                lda   $E0C068            turn on bank $01 direct page & stack
  305.                ora   #$30
  306.                sta   $E0C068
  307.                longm
  308.  
  309.                lda   #$9CFF
  310.                tcs
  311.  
  312.                lda   #$9C00
  313.                tcd
  314.  
  315.                brl   Start5E
  316.  
  317. loop           anop
  318.                pei   $FE
  319.                pei   $FC
  320.                pei   $FA
  321.  
  322.                ...                      all the inbetween pei's...
  323.  
  324.                pei   $60
  325. Start5E        pei   $5E
  326.                pei   $5C
  327.  
  328.                ...
  329.  
  330.                pei   $04
  331.                pei   $02
  332.                pei   $00
  333.  
  334.                sec
  335.                sbc   #$100              subtract $100 from the DP register
  336. ! we don't have to do tdc before this cuz the accm already has the DP reg in it
  337.                cmp   #$2000             done the whole screen yet?
  338.                blt   Yes
  339.                tcd
  340.                brl   loop
  341.  
  342. Yes            anop
  343.  
  344.                shortm
  345.                lda   $E0C035            turn off SHR shadowing
  346.                ora   #$08
  347.                sta   $E0C035
  348.                lda   $E0C068            turn off bank $01 dp/stack
  349.                and   #$CF
  350.                sta   $E0C068
  351.                longm
  352.  
  353.                lda   StackTemp          restore original stack pointer
  354.                tcs
  355.                pld                      restore original direct page pointer
  356.  
  357.                plp                      restore original interrupt status
  358.  
  359.                ... (your code here)
  360.  
  361. StackTemp      ds    2
  362.  
  363.  
  364.                Here is an explanation I wrote earlier in the Photon code
  365. segment source code.  I am sorry that it uses $5100 and $51FF as an example
  366. instead of $9C00 and $9CFF that are used in the above source, but I don't feel
  367. like re-frying my brain out to rewrite it.  I just am not to interested in
  368. having my head explode. :)
  369.  
  370. *      For instance, if I set the direct page to $5100 and the stack to $51FF,
  371. *      and then do a PEI $5E, what is happening is:
  372. *           the value at the direct page register + $5E, in this case it's
  373. *           $515E,is stored (pushed)to the address of the stack decremented, or
  374. *           in this case $51FE.  Now, graphics line $4F starts at $5160, and
  375. *           line $50 starts at $5200.  What is actually happening is the last
  376. *           four pixels (one word) of line $4F are being stored in exactly the
  377. *           same physical location one line down, all at an incredible speed
  378. *           improvement over loading and storing to bank E1 using absolute
  379. *           indexed with X or absolute long indexed with X addressing.  Note
  380. *           that 5E and FE are exactly A0 (160) bytes apart; the length of one
  381. *           line of graphics in memory.
  382. *      Then I PEI additional values until we have done a PEI $00.  Then I
  383. *      subtract $100 from the direct page (I don't need to subtract anything
  384. *      from the stack as it is automatically incremented/decremented) and
  385. *      repeat starting at PEI $FE (since we've already established our A0 byte
  386. *      (1 line) variance, I don't need to start at PEI $5E again) until I
  387. *      detect that we've moved the entire shape exactly one line down, by
  388. *      checking if the direct page register is less than the end of the SHR        pixel dat
  389. *      pixel data.
  390.  
  391.  
  392.                That's about it for Version 1.1 of DYA TechNote #3.  In the
  393. future, I might write an Advanced Animation Techniques TechNote, when I learn
  394. more advanced techniques.  If you like this, please tell me, as if noone says
  395. anything, I probably won't write (or won't release) other possible TechNotes.
  396.  
  397. Jim Maricondo                                                      June 10, 1990
  398.  
  399.  
  400. CONTACTS:
  401. America Online: `DYA Jim`
  402. GEnie:          `J.Maricondo1`
  403.  
  404. ___________________
  405. Further References: (let's face it there isn't a lot of stuff on animation!)
  406.  
  407. o Call Apple Winter 1989/1990, pages 8 thru 23.
  408. o Apple IIgs Hardware Reference, pages 55 thru 99.
  409. o Apple IIgs TechNote #70.
  410.  
  411.